package com.ruoyi.pay.wx.service.Impl;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.pay.domain.PayOrder;
import com.ruoyi.pay.wx.config.WxJsApiPayConfig;
import com.ruoyi.pay.wx.config.WxPayConfig;
import com.ruoyi.pay.wx.service.IWxJsApiPayService;
import com.wechat.pay.java.core.cipher.Signer;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.util.NonceUtil;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.time.Instant;

@Service("pay:service:wxJsApi")
@ConditionalOnProperty(prefix = "pay.wxJsApi", name = "enabled", havingValue = "true")
@Slf4j
public class WxJsApiPayServiceImpl implements IWxJsApiPayService {

    @Autowired
    private JsapiService jsapiService;
    @Autowired
    private WxJsApiPayConfig wxJsApiPayConfig;

    @Override
    public String notify(HttpServletRequest servletRequest, HttpServletResponse response, PayOrder payOrder, String type) throws Exception {
        return "";
    }

    @Override
    public PayOrder query(PayOrder payOrder) {
        return null;
    }

    @Override
    public PayOrder refund(PayOrder payOrder) {
        return null;
    }

    /**
     * JSAPI 支付下单，并返回 JSAPI 调起支付数据。推荐使用！
     *
     * <p>请求成功后，该方法返回预支付交易会话标识 prepay_id 和客户端 JSAPI 调起支付所需参数。 它相比 JsApiService.prepay
     * 更简单易用，因为无需开发者自行计算调起支付签名。
     *
     * @param payOrder 请求参数
     * @return PrepayWithRequestPaymentResponse
     * @throws HttpException 发送HTTP请求失败。例如构建请求参数失败、发送请求失败、I/O错误等。包含请求信息。
     * @throws ValidationException 发送HTTP请求成功，验证微信支付返回签名失败。
     * @throws ServiceException 发送HTTP请求成功，服务返回异常。例如返回状态码小于200或大于等于300。
     * @throws MalformedMessageException 服务返回成功，content-type不为application/json、解析返回体失败。
     */
    @Override
    public String payUrl(PayOrder payOrder) {
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(Integer.parseInt(payOrder.getTotalAmount()));
        request.setAmount(amount);
        request.setAppid(wxJsApiPayConfig.getAppId());
        request.setMchid(wxJsApiPayConfig.getMerchantId());
        request.setDescription(payOrder.getOrderContent());
        StringBuilder notifyUrlBuilder = new StringBuilder();
        String orderNotifyUrl = notifyUrlBuilder.append(wxJsApiPayConfig.getNotifyUrl())
                .append("/").append(payOrder.getOrderNumber())
                .append("/pay").toString();
        request.setNotifyUrl(orderNotifyUrl);
        request.setOutTradeNo(payOrder.getOrderNumber());
        Payer payer = new Payer();
        payer.setOpenid(payOrder.getPayBy());
        request.setPayer(payer);
        String prepayId = jsapiService.prepay(request).getPrepayId();
        long timestamp = Instant.now().getEpochSecond();
        String nonceStr = NonceUtil.createNonce(32);
        String packageVal = "prepay_id=" + prepayId;
        String message =
                request.getAppid() + "\n" + timestamp + "\n" + nonceStr + "\n" + packageVal + "\n";
        log.debug("Message for RequestPayment signatures is[{}]", message);
        Signer signer = null;
        try {
            signer = wxJsApiPayConfig.wxJsapipayBaseConfig().createSigner();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String sign = signer.sign(message).getSign();
        JSONObject response = new JSONObject();
        response.put("appid",request.getAppid());
        response.put("timestamp",String.valueOf(timestamp));
        response.put("nonceStr",nonceStr);
        response.put("packageVal",packageVal);
        response.put("signType","RSA");
        response.put("paySign",sign);
        return response.toJSONString();
    }
    /**
     * 微信支付订单号查询订单
     *
     * @param request 请求参数
     * @return Transaction
     * @throws HttpException 发送HTTP请求失败。例如构建请求参数失败、发送请求失败、I/O错误等。包含请求信息。
     * @throws ValidationException 发送HTTP请求成功，验证微信支付返回签名失败。
     * @throws ServiceException 发送HTTP请求成功，服务返回异常。例如返回状态码小于200或大于等于300。
     * @throws MalformedMessageException 服务返回成功，content-type不为application/json、解析返回体失败。
     */
    public Transaction queryOrderById(QueryOrderByIdRequest request) {
        return jsapiService.queryOrderById(request);
    }
    /**
     * 商户订单号查询订单
     *
     * @param request 请求参数
     * @return Transaction
     * @throws HttpException 发送HTTP请求失败。例如构建请求参数失败、发送请求失败、I/O错误等。包含请求信息。
     * @throws ValidationException 发送HTTP请求成功，验证微信支付返回签名失败。
     * @throws ServiceException 发送HTTP请求成功，服务返回异常。例如返回状态码小于200或大于等于300。
     * @throws MalformedMessageException 服务返回成功，content-type不为application/json、解析返回体失败。
     */
    public Transaction queryOrderByOutTradeNo(QueryOrderByOutTradeNoRequest request) {
        return jsapiService.queryOrderByOutTradeNo(request);
    }
    /**
     * 关闭订单
     *
     * @param request 请求参数
     * @throws HttpException 发送HTTP请求失败。例如构建请求参数失败、发送请求失败、I/O错误等。包含请求信息。
     * @throws ValidationException 发送HTTP请求成功，验证微信支付返回签名失败。
     * @throws ServiceException 发送HTTP请求成功，服务返回异常。例如返回状态码小于200或大于等于300。
     * @throws MalformedMessageException 服务返回成功，content-type不为application/json、解析返回体失败。
     */
    public void closeOrder(CloseOrderRequest request) {
        jsapiService.closeOrder(request);
    }

}
